From a83037c440bbc7408d8ed36e7dc2f11b2c191938 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Mon, 11 Dec 2017 08:22:28 +0100 Subject: [PATCH] gl renderer: Implement cross fade nodes --- gsk/gl/gskglrenderer.c | 66 ++++++++++++++++++++++++++- gsk/gl/gskglrenderopsprivate.h | 15 ++++-- gsk/meson.build | 1 + gsk/resources/glsl/cross_fade.fs.glsl | 12 +++++ 4 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 gsk/resources/glsl/cross_fade.fs.glsl diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index f0f5508dc7..c9acda79c5 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -199,6 +199,7 @@ struct _GskGLRenderer Program outset_shadow_program; Program shadow_program; Program border_program; + Program cross_fade_program; }; }; @@ -992,6 +993,51 @@ render_shadow_node (GskGLRenderer *self, gsk_gl_renderer_add_render_ops (self, original_child, builder); } +static inline void +render_cross_fade_node (GskGLRenderer *self, + GskRenderNode *node, + RenderOpBuilder *builder) +{ + const float min_x = node->bounds.origin.x; + const float min_y = node->bounds.origin.y; + const float max_x = min_x + node->bounds.size.width; + const float max_y = min_y + node->bounds.size.height; + GskRenderNode *start_node = gsk_cross_fade_node_get_start_child (node); + GskRenderNode *end_node = gsk_cross_fade_node_get_end_child (node); + float progress = gsk_cross_fade_node_get_progress (node); + int start_texture_id; + int end_texture_id; + gboolean is_offscreen; + RenderOp op; + const GskQuadVertex vertex_data[GL_N_VERTICES] = { + { { min_x, min_y }, { 0, 1 }, }, + { { min_x, max_y }, { 0, 0 }, }, + { { max_x, min_y }, { 1, 1 }, }, + + { { max_x, max_y }, { 1, 0 }, }, + { { min_x, max_y }, { 0, 0 }, }, + { { max_x, min_y }, { 1, 1 }, }, + }; + + /* TODO: We create 2 textures here as big as the cross-fade node, but both the + * start and the end node might be a lot smaller than that. */ + + add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y, start_node, + &start_texture_id, &is_offscreen); + + add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y, end_node, + &end_texture_id, &is_offscreen); + + ops_set_program (builder, &self->cross_fade_program); + op.op = OP_CHANGE_CROSS_FADE; + op.cross_fade.progress = progress; + op.cross_fade.source2 = end_texture_id; + ops_add (builder, &op); + ops_set_texture (builder, start_texture_id); + + ops_draw (builder, vertex_data); +} + static void gsk_gl_renderer_dispose (GObject *gobject) { @@ -1073,6 +1119,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, { "outset shadow", "blit.vs.glsl", "outset_shadow.fs.glsl" }, { "shadow", "blit.vs.glsl", "shadow.fs.glsl" }, { "border", "blit.vs.glsl", "border.fs.glsl" }, + { "cross fade", "blit.vs.glsl", "cross_fade.fs.glsl" }, }; builder = gsk_shader_builder_new (); @@ -1190,6 +1237,10 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, INIT_PROGRAM_UNIFORM_LOCATION (border, color); INIT_PROGRAM_UNIFORM_LOCATION (border, widths); + /* cross fade */ + INIT_PROGRAM_UNIFORM_LOCATION (cross_fade, progress); + INIT_PROGRAM_UNIFORM_LOCATION (cross_fade, source2); + g_object_unref (builder); return TRUE; } @@ -1510,8 +1561,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self, render_border_node (self, node, builder); break; - case GSK_REPEATING_LINEAR_GRADIENT_NODE: case GSK_CROSS_FADE_NODE: + render_cross_fade_node (self, node, builder); + break; + + case GSK_REPEATING_LINEAR_GRADIENT_NODE: case GSK_BLEND_NODE: case GSK_REPEAT_NODE: default: @@ -1770,6 +1824,16 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self, break; + case OP_CHANGE_CROSS_FADE: + g_assert (program == &self->cross_fade_program); + /* End texture id */ + glUniform1i (program->cross_fade.source2_location, 1); + glActiveTexture (GL_TEXTURE0 + 1); + glBindTexture (GL_TEXTURE_2D, op->cross_fade.source2); + /* progress */ + glUniform1f (program->cross_fade.progress_location, op->cross_fade.progress); + break; + case OP_CHANGE_LINEAR_GRADIENT: OP_PRINT (" -> Linear gradient"); glUniform1i (program->linear_gradient.num_color_stops_location, diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index 89dca55a24..5081a0c0e5 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -10,7 +10,7 @@ #include "gskglrendererprivate.h" #define GL_N_VERTICES 6 -#define GL_N_PROGRAMS 11 +#define GL_N_PROGRAMS 12 enum { OP_NONE, @@ -31,8 +31,9 @@ enum { OP_CHANGE_OUTSET_SHADOW = 15, OP_CHANGE_BORDER = 16, OP_CHANGE_BORDER_COLOR = 17, - OP_CLEAR = 18, - OP_DRAW = 19, + OP_CHANGE_CROSS_FADE = 18, + OP_CLEAR = 19, + OP_DRAW = 20, }; typedef struct @@ -99,6 +100,10 @@ typedef struct int color_location; int widths_location; } border; + struct { + int source2_location; + int progress_location; + } cross_fade; }; } Program; @@ -162,6 +167,10 @@ typedef struct float widths[4]; float color[4]; } border; + struct { + float progress; + int source2; + } cross_fade; }; } RenderOp; diff --git a/gsk/meson.build b/gsk/meson.build index 7f0ff2682c..8ee5af949c 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -13,6 +13,7 @@ gsk_private_source_shaders = [ 'resources/glsl/outset_shadow.fs.glsl', 'resources/glsl/shadow.fs.glsl', 'resources/glsl/border.fs.glsl', + 'resources/glsl/cross_fade.fs.glsl', 'resources/glsl/es2_common.fs.glsl', 'resources/glsl/es2_common.vs.glsl', 'resources/glsl/gl3_common.fs.glsl', diff --git a/gsk/resources/glsl/cross_fade.fs.glsl b/gsk/resources/glsl/cross_fade.fs.glsl new file mode 100644 index 0000000000..a38b504a6c --- /dev/null +++ b/gsk/resources/glsl/cross_fade.fs.glsl @@ -0,0 +1,12 @@ + +uniform float u_progress; +uniform sampler2D u_source2; + +void main() { + vec4 source1 = Texture(u_source, vUv); // start child + vec4 source2 = Texture(u_source2, vUv); // end child + + float p = u_progress; + vec4 color = ((1 - p) * source1) + (p * source2); + setOutputColor(color); +} -- 2.30.2